const tvvsdk_constants = require('./tvvsdk_constants.js')
const tvRtcPlugin = require('./tvrtc.es.js')
const getStats = require('./getStats.js')
const tvConstants = tvvsdk_constants.constants
const tvMessageConstants = tvvsdk_constants.messageConstants
const tvTipsConstants = tvvsdk_constants.tipsConstants
const tvRTC = tvRtcPlugin.default
// 默认分辨率
let width = 640
let height = 360
let confminbr = 300000
let confmaxbr = 1500000
let conffps = 15
let confmode = 0
let picmode = 0
// 用户自定义的视频选项
let userOptions
let urlOptions
const TAG = 'tvLog core-------'
const opaqueId = 'videoroomtest-' + tvRTC.randomString(12)
const myCallbacks = {}
const feeds = []
let myName
let isShareScreen = false
let videoSend = true
let audioSend = true
const symbols = '$zwan$'
let localGetStatusResult
const remoteGetStatusResultArray = []
const pluginName = 'zwan.service.videoroom'
// crateConnection 所需
const resp = {}
const websocketServer = 'ws://192.168.2.59:9002/webrtc/websocket'
let tvWs
const heartBeat = 'heartBeat'
let wsMessageCallback
let getOnlineUsersCallback
let singleMessageCallback
let roomMessageCallback

function exeInit(options, callback) {
  console.log(TAG, 'exeInit')
  callback = callback || tvRTCMethod.noop
  var resp = {
    success: false,
    msg: tvTipsConstants.initFailed
  }
  if (!tvRTC.isWebrtcSupported()) {
    resp.msg = tvTipsConstants.notSupportWebRtc
    return callback(resp)
  }
  if (!options) {
    resp.msg = tvTipsConstants.pleaseSetOptionsValue
    return callback(resp)
  }
  urlOptions = options
  // 全局赋值
  console.log('urlOptions参数')
  console.log(TAG, urlOptions)

  tvRTC.init({
    debug: true,
    callback: function() {
      resp.success = true
      resp.msg = tvTipsConstants.initSuccess
      return callback(resp)
    }
  })
}

function exeLogin(username, platform, callback) {
  console.log(TAG, 'exeLogin')
  userOptions.platform = platform
  userOptions.username = username
  const resp = {
    success: false
  }
  if ('WebSocket' in window) {
    const certificate = username + symbols + platform
    tvWs = new WebSocket(websocketServer + '/' + certificate)
    tvWs.onopen = function() {
      resp.success = true
      resp.msg = 'ws connection success'
      // 建立连接
      callback(resp)
      tvWs.send(heartBeat)
    }
    tvWs.onmessage = function(evt) {
      console.log(evt.data)
      const message = JSON.parse(evt.data)
      if (message) {
        // 单发消息回调
        if (message.operation === tvMessageConstants.typeSingle && singleMessageCallback) {
          resp.success = message.success
          resp.msg = message.msg
          singleMessageCallback(resp)
          return
        }
        if (message.operation === tvMessageConstants.typeGetOnLineUsers && getOnlineUsersCallback) {
          resp.success = message.success
          resp.msg = message.msg
          if (message.success) {
            resp.data = message.data
          }
          getOnlineUsersCallback(resp)
          return
        } else if (message.operation === tvMessageConstants.operationRepeatLogin) {
          exeLoginOut()
          if (wsMessageCallback) {
            wsMessageCallback.repeatlogin()
          }
          return
        } else if (message.operation === tvMessageConstants.typeRoom && roomMessageCallback) {
          // 会议房间消息
          resp.success = message.success
          resp.msg = message.msg
          roomMessageCallback(resp)
        } else {
          if (wsMessageCallback) { wsMessageCallback.onmessage(message.sender, message.platform, message.operation, message.content) }
        }
      }
    }

    tvWs.onclose = function() {
      console.log('ws close...')
      tvWs = null
    }
  } else {
    resp.msg = tvTipsConstants.websocketError
    callback(resp)
  }
}

function exeSendRoomMessage(roomId, operation, content, callback) {
  console.log(TAG, 'exeSendRoomMessage')
  roomMessageCallback = callback
  const resp = {}
  if (tvWs) {
    const request = {}
    request.roomId = roomId
    request.platform = userOptions.platform
    request.sender = userOptions.username
    request.type = tvMessageConstants.typeRoom
    request.operation = operation
    request.content = content
    try {
      tvWs.send(JSON.stringify(request))
    } catch (err) {
      resp.success = false
      resp.msg = err
      callback(resp)
    }
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.pleaseConnectionServer
    callback(resp)
  }
}

function exeLoginOut() {
  console.log(TAG, 'exeLoginOut')
  if (tvWs) {
    tvWs.close()
  }
}

function exeGetOnlineUsers(callback) {
  console.log(TAG, 'exeGetOnlineUsers')
  const resp = {}
  if (tvWs) {
    const request = {}
    request.type = tvMessageConstants.typeGetOnLineUsers
    request.sender = userOptions.username
    request.platform = userOptions.platform
    try {
      tvWs.send(JSON.stringify(request))
      getOnlineUsersCallback = callback
    } catch (err) {
      resp.success = false
      resp.msg = err
      callback(resp)
    }
  } else {
    resp.success = false
    resp.msg = tvConstants.websocketError
    callback(resp)
  }
}

function exeJoinRoom(sessionId, roomId, name, callbacks) {
  console.log(TAG, 'exeJoinRoom roomId=' + roomId + ',name=' + name)
  myName = name
  console.log(callbacks)
  callbacks.onlocalstream =
		typeof callbacks.onlocalstream === 'function' ? callbacks.onlocalstream : tvRTCMethod.noop
  callbacks.onremotestream =
		typeof callbacks.onremotestream === 'function' ? callbacks.onremotestream : tvRTCMethod.noop
  callbacks.onleave =
		typeof callbacks.onleave === 'function' ? callbacks.onleave : tvRTCMethod.noop
  callbacks.onjoined =
		typeof callbacks.onjoined === 'function' ? callbacks.onjoined : tvRTCMethod.noop
  callbacks.ondata =
		typeof callbacks.ondata === 'function' ? callbacks.ondata : tvRTCMethod.noop
  callbacks.onsharescreen =
		typeof callbacks.onsharescreen === 'function' ? callbacks.onsharescreen : tvRTCMethod.noop
  myCallbacks[sessionId] = callbacks
  const displayName = name
  var join = {
    request: 'join',
    room: roomId,
    authid: displayName,
    display: displayName
  }
  tvRTC.sessions[sessionId].pluginHandler().send({
    message: join
  })
}

function exeQueryRoom(sessionId, roomId, callback) {
  const callbacks = {
    message: { 'request': 'query', 'room': roomId },
    success: function(result) {
      if (result.type !== 'queryresult') {
        console.log(TAG, 'not expect msg for exeQueryRoom')
        return
      }
      result.participants.sort(function(user1, user2) {
        return user1.position - user2.position
      })

      if (callback) { callback.success(result) }
    },
    error: function(error) {
      console.log(error)
      if (callback) {
        if (error.msg) {
          callback.error(error.msg)
        } else {
          callback.error(error)
        }
      }
    }
  }
  tvRTC.sessions[sessionId].pluginHandler().send(callbacks)
}
function exeCompositeRoom(sessionId, roomId, userList, callback) {
  const participants = []
  userList.forEach(function(user) {
    const u = {}
    u.display = user.userName
    u.id = user.id
    u.position = user.position
    participants.push(u)
  })
  const composite = {}
  composite.participants = participants
  composite.room = roomId
  composite.request = 'composite'

  const callbacks = {
    message: composite,
    success: function(result) {
      if (callback) {
        callback.success()
      }
    },
    error: function(error) {
      console.log(error)
      if (callback) {
        callback.error(error.msg)
      }
    }
  }
  tvRTC.sessions[sessionId].pluginHandler().send(callbacks)
}
function exeQueryDevice(sessionId, callback) {
  const callbacks = {
    message: { 'request': 'querydevice' },
    success: function(result) {
      if (result.type !== 'querydeviceresult') {
        console.log(TAG, 'not expect msg for exeQueryDevice')
        return
      }

      if (callback) {
        result.success = true
        callback(result)
      }
    },
    error: function(error) {
      console.log(error)
      if (callback) {
        callback.error(error.msg)
      }
    }
  }
  tvRTC.sessions[sessionId].pluginHandler().send(callbacks)
}

function exeAttachMediaStream(videoObj, stream) {
  console.log(TAG, 'exeAttachMediaStream')
  tvRTC.attachMediaStream(videoObj, stream)
}

function exeShareScreen(sessionId, enable, callback) {
  console.log(TAG, 'exeShareScreen')
  if (enable) {
    startShareScreen(sessionId, callback)
  } else {
    closeShareScreen(sessionId, callback)
  }
}

function exeMike(sessionId, enable, callback) {
  console.log(TAG, 'exeMike ' + enable)
  let media
  var resp = {}
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    resp.success = true
    const createOfferCallbacks = {
      success: function(jsep) {
        resp.success = true
        var publish = {
          'request': 'configure'
        }
        if (enable) {
          publish.audio = true
        } else {
          publish.audio = false
        }
        audioSend = enable
        tvRTC.sessions[sessionId].pluginHandler().send({
          'message': publish,
          'jsep': jsep
        })
        if (callback) { callback(resp) }
      },
      error: function(error) {
        resp.success = false
        resp.msg = error
        if (callback) { return callback(resp) }
      }
    }
    if (enable) {
      media = {
        replaceAudio: true,
        audio: userOptions.audio,
        video: { type: 'camera' }
      }
    } else {
      media = {
        removeAudio: true,
        audio: userOptions.audio,
        video: { type: 'camera' }
      }
    }
    console.log(TAG, media)
    createOfferCallbacks.media = media
    tvRTC.sessions[sessionId].pluginHandler().createOffer(createOfferCallbacks)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.pleaseConnectionServer
  }
  if (callback) { callback(resp) }
}

function exePublish(sessionId, enable, callback) {
  console.log(TAG, 'exePublish ' + enable)
  cleanUserOption()
  let media = userOptions
  const resp = {}
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    resp.success = true
    const createOfferCallbacks = {
      success: function(jsep) {
        resp.success = true
        // var publish = {
        // 	"request": "configure",
        // };
        // if (enable) {
        // 	publish.video = true;
        // } else {
        // 	publish.video = false;
        // }
        // sfuPlugin.send({
        // 	"message": publish,
        // 	"jsep": jsep
        // });
        // 更新状态
        videoSend = enable
        // alert(videoSend)
        // 更新media状态
        userOptions.video.videoSend = videoSend
        if (callback) { callback(resp) }
      },
      error: function(error) {
        resp.success = false
        resp.msg = error
        if (callback) { return callback(resp) }
      }
    }
    if (enable) {
      media.video.type = 'camera'
      media.replaceVideo = true
      media.videoSend = true
      media.audioSend = audioSend
    } else {
      media = {
        removeVideo: true,
        videoSend: false
      }
    }
    console.log(TAG, media)
    createOfferCallbacks.media = media
    tvRTC.sessions[sessionId].pluginHandler().createOffer(createOfferCallbacks)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.pleaseConnectionServer
    if (callback) { callback(resp) }
  }
}

function cleanUserOption() {
  if (userOptions) {
    delete userOptions.update
    delete userOptions.keepAudio
    delete userOptions.keepVideo
    delete userOptions.replaceAudio
    delete userOptions.replaceVideo
    delete userOptions.addAudio
    delete userOptions.removeAudio
    delete userOptions.addVideo
    delete userOptions.removeVideo
  }
}

function exeSetResolution(sessionId, resolution, callback) {
  console.log(TAG, 'exeSetResolution')
  cleanUserOption()
  const resp = {}
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    userOptions.video.size = resolution
    userOptions.replaceVideo = true
    userOptions.replaceAudio = true

    const callbacks = {
      media: userOptions,
      success: function(jsep) {
        if (callback) { callback(resp) }
      },
      error: function(error) {
        console.log(error)
        resp.success = false
        resp.msg = error.name
        if (callback) { callback(resp) }
      }
    }
    tvRTC.sessions[sessionId].pluginHandler().createOffer(callbacks)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.notInit
  }
  if (callback) { callback(resp) }
}

function exeSetBitrate(sessionId, bitrate, callback) {
  console.log(TAG, 'exeSetBitrate:' + bitrate)
  cleanUserOption()
  const resp = {}
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    const callbacks = {
      bandwidth: bitrate,
      success: function() {
        resp.success = true
        if (callback) { callback(resp) }
      },
      error: function(error) {
        console.log(error)
        resp.success = false
        resp.msg = error.name
        if (callback) { callback(resp) }
      }
    }
    tvRTC.sessions[sessionId].pluginHandler().setBitrate(callbacks)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.notInit
  }
  if (callback) { callback(resp) }
}

function exeReconfigConf(sessionId, roomId, confSize, confBr, confFps, callback) {
  console.log(TAG, 'exeReconfigConf size:' + confSize + ' bitrate:' + confBr + ' fps:' + confFps)
  let height = 360; let width = 640
  if (confSize === 'lowres') {
    // Small resolution, 4:3
    height = 240
    width = 320
  } else if (confSize === 'hires' || confSize === 'hires-16:9' || confSize === 'hdres') {
    height = 720
    width = 1280
  } else if (confSize === 'fhdres') {
    height = 1080
    width = 1920
  } else if (confSize === 'lowres-16:9') {
    height = 360
    width = 640
  } else if (confSize === 'stdres-16:9') {
    height = 540
    width = 960
  } else {
    height = 360
    width = 640
  }

  var reconfig = {
    request: 'reconfig',
    room: roomId.toString(),
    mcufps: confFps,
    mcuwidth: width,
    mcuheight: height,
    mcuminbr: 300 * 1024,
    mcuinitbr: confBr,
    mcumaxbr: confBr
  }
  tvRTC.sessions[sessionId].pluginHandler().send({
    message: reconfig
  })
}

function exeGetAllDevices(callback) {
  console.log(TAG, 'exeGetAllDevices')
  tvRTC.listDevices(callback)
}

let first_duration = 0
let last_duration = 0
let last_send_bytes = 0
let last_recv_bytes = 0
let last_send_frame = 0
let last_recv_frame = 0

function getQosString(reports) {
  const results = []
  let duration = 0; let sendbr = 0; let recvbr = 0; let sendfps = 0; let recvfps = 0
  let sendbytes = 0; let recvbytes = 0
  let localframe = 0; let remoteframe = 0
  if (!reports) { return }

  reports.forEach(report => {
    if (report.type === 'inbound-rtp') {
      if (report.mediaType === 'audio') {
        results.push({ 'name': '音频接收字节', 'value': report.bytesReceived, 'index': 1 })
        results.push({ 'name': '音频收包数', 'value': report.packetsReceived, 'index': 2 })
        results.push({ 'name': '音频丢包数', 'value': report.packetsLost, 'index': 3 })
      } else if (report.mediaType === 'video') {
        results.push({ 'name': '视频接收字节', 'value': report.bytesReceived, 'index': 6 })
        results.push({ 'name': '视频收包数', 'value': report.packetsReceived, 'index': 7 })
        results.push({ 'name': '视频丢包数', 'value': report.packetsLost, 'index': 8 })
        results.push({ 'name': '接收FIR数', 'value': report.firCount, 'index': 11 })
        results.push({ 'name': '接收PLI数', 'value': report.pliCount, 'index': 12 })
        results.push({ 'name': '接收NACK数', 'value': report.nackCount, 'index': 13 })
        recvbytes = report.bytesReceived
      }
    } else if (report.type === 'outbound-rtp') {
      if (report.mediaType === 'audio') {
        results.push({ 'name': '音频发送字节', 'value': report.bytesSent, 'index': 4 })
        results.push({ 'name': '音频发包数', 'value': report.packetsSent, 'index': 5 })
      } else if (report.mediaType === 'video') {
        results.push({ 'name': '视频发送字节', 'value': report.bytesSent, 'index': 9 })
        results.push({ 'name': '视频发包数', 'value': report.packetsSent, 'index': 10 })
        results.push({ 'name': '发送FIR数', 'value': report.firCount, 'index': 14 })
        results.push({ 'name': '发送PLI数', 'value': report.pliCount, 'index': 15 })
        results.push({ 'name': '发送NACK数', 'value': report.nackCount, 'index': 16 })
        sendbytes = report.bytesSent
      }
    } else if (report.type === 'track') {
      if (report.remoteSource === false && report.kind === 'video') {
        results.push({ 'name': '本地视频尺寸', 'value': report.frameWidth + '*' + report.frameHeight, 'index': 17 })
        results.push({ 'name': '本地视频发送帧数', 'value': report.framesSent, 'index': 18 })
        localframe = report.framesSent
      } else if (report.remoteSource === true && report.kind === 'video') {
        results.push({ 'name': '远端视频尺寸', 'value': report.frameWidth + '*' + report.frameHeight, 'index': 19 })
        results.push({ 'name': '远端视频接收帧数', 'value': report.framesReceived, 'index': 20 })
        remoteframe = report.framesReceived
        duration = report.timestamp
        if (first_duration === 0) {
          first_duration = report.timestamp
        }
      }
    }
  })
  if (last_duration !== 0) {
    // 计算比特率
    const time = (duration - last_duration) / 1000
    if (time !== 0) {
      sendbr = 8 * (sendbytes - last_send_bytes) / time / 1024
      recvbr = 8 * (recvbytes - last_recv_bytes) / time / 1024
      results.push({ name: '视频发送码率', 'value': sendbr.toFixed(1), 'index': 21 })
      results.push({ name: '视频接收码率', 'value': recvbr.toFixed(1), 'index': 22 })
    }

    // 计算帧率
    if (time !== 0) {
      sendfps = (localframe - last_send_frame) / time
      recvfps = (remoteframe - last_recv_frame) / time
      results.push({ name: '视频发送帧率', 'value': sendfps.toFixed(0), 'index': 23 })
      results.push({ name: '视频接收帧率', 'value': recvfps.toFixed(0), 'index': 24 })
    }
  } else {
    results.push({ name: '视频发送码率', 'value': 0.0, 'index': 21 })
    results.push({ name: '视频接收码率', 'value': 0.0, 'index': 22 })
    results.push({ name: '视频发送帧率', 'value': 0, 'index': 23 })
    results.push({ name: '视频接收帧率', 'value': 0, 'index': 24 })
  }
  const t = (duration - first_duration) / 1000
  results.push({ name: '视频时间', 'value': t.toFixed(1), 'index': 25 })
  results.sort(function(a, b) {
    return a.index > b.index
  })
  last_duration = duration
  last_send_bytes = sendbytes
  last_recv_bytes = recvbytes
  last_send_frame = localframe
  last_recv_frame = remoteframe
  return results
}

function exeInitQos() {
  last_duration = 0
  first_duration = 0
  last_send_bytes = 0
  last_recv_bytes = 0
  last_send_frame = 0
  last_recv_frame = 0
}

function exeGetQos(sessionId, callback) {
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    const callbacks = {
      success: function(reports) {
        resp.success = true
        resp.report = getQosString(reports)
        if (callback) { callback(resp) }
      },
      error: function(error) {
        console.log(error)
        resp.success = false
        resp.msg = error.name
        if (callback) { callback(resp) }
      }
    }
    tvRTC.sessions[sessionId].pluginHandler().getQos(callbacks)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.notInit
  }
  if (callback) { callback(resp) }
}

function exeStartLocalQos(sessionId, callback) {
  console.log(TAG, 'exeStartLocalQos')
  const resp = {}
  const repeatInterval = 1000
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    getStats(tvRTC.sessions[sessionId].pluginHandler().webrtcStuff.pc, function(result) {
      resp.success = true
      //	console.log(result);
      localGetStatusResult = result
      const sendWidth = result.resolutions.send.width
      const sendHeight = result.resolutions.send.height
      // let videoBytesSent = result.video.bytesSent;
      // let audioBytesSent = result.audio.bytesSent;
      const videoBytesSent = (result.video.bytesSent / 1024 / 1024).toFixed(2)
      const audioBytesSent = (result.audio.bytesSent / 1024 / 1024).toFixed(2)
      // let speed = result.bandwidth.speed;
      const speed = (result.bandwidth.speed / 1024).toFixed(0)
      const videoCodec = result.audio.send.codecs
      const audioCodec = result.video.send.codecs
      const videoPacketsLost = (result.video.packetsLost / 1024).toFixed(2)
      const audioPacketsLost = (result.audio.packetsLost / 1024).toFixed(2)
      const videolatency = result.video.latency
      const audioLatency = result.audio.latency
      const data = {
        // 发送数据总大小
        total: {
          audio: audioBytesSent,
          video: videoBytesSent,
          unit: 'MB'
        },
        // 带宽
        bandwidth: {
          speed: speed,
          unit: 'KB/s'
        },
        // 编码
        codesc: {
          audio: audioCodec,
          video: videoCodec
        },
        // 丢包
        packetsLost: {
          video: videoPacketsLost,
          audio: audioPacketsLost,
          unit: 'KB'
        },
        // 延迟
        latency: {
          audio: audioLatency,
          video: videolatency,
          unit: 'ms'
        }
      }
      const resolution = {
        width: sendWidth,
        height: sendHeight
      }
      data.resolution = resolution
      resp.data = data
      callback(resp)
    }, repeatInterval)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.pleaseConnectionServer
    callback(resp)
  }
}

function exeStopLocalQos() {
  console.log(TAG, 'exeStopLocalQos')
  if (localGetStatusResult) {
    localGetStatusResult.nomore()
  }
}

function exeStartRemoteQos(index, callback) {
  console.log(TAG, 'exeStartRemoteQos')
  const resp = {}
  if (index > 0) {
    var repeatInterval = 1000 // 2000 ms == 2 seconds
    const remoteFeed = feeds[index]
    console.log(remoteFeed)
    if (remoteFeed) {
      getStats(remoteFeed.webrtcStuff.pc, function(result) {
        // console.log(result);
        resp.success = true
        remoteGetStatusResultArray[index] = result
        const sendWidth = result.resolutions.recv.width
        const sendHeight = result.resolutions.recv.height
        // let videoBytesSent = (result.video.bytesSent;
        // let audioBytesSent = (result.audio.bytesSent;
        const videoBytesSent = (result.video.bytesReceived / 1024 / 1024).toFixed(2)
        const audioBytesSent = (result.audio.bytesReceived / 1024 / 1024).toFixed(2)
        const videoCodec = result.audio.recv.codecs
        const audioCodec = result.video.recv.codecs
        const videoPacketsLost = (result.video.packetsLost / 1024).toFixed(2)
        const audioPacketsLost = (result.audio.packetsLost / 1024).toFixed(2)
        const videolatency = result.video.latency
        const audioLatency = result.audio.latency
        const speed = remoteFeed.getBitrate()
        const data = {
          // 发送数据总大小
          total: {
            audio: audioBytesSent,
            video: videoBytesSent,
            unit: 'MB'
          },
          codesc: {
            audio: audioCodec,
            video: videoCodec
          },
          // 丢包
          packetsLost: {
            video: videoPacketsLost,
            audio: audioPacketsLost,
            unit: 'KB'
          },
          // 延迟
          latency: {
            audio: audioLatency,
            video: videolatency,
            unit: 'ms'
          }, // 带宽
          bandwidth: {
            speed: speed
          }
        }

        const resolution = {
          width: sendWidth,
          height: sendHeight
        }
        data.resolution = resolution
        resp.data = data
        callback(resp)
      }, repeatInterval)
    } else {
      resp.success = false
      resp.msg = 'remote is null'
      callback(resp)
    }
  } else {
    resp.success = false
    resp.msg = 'index must > 0'
    callback(resp)
  }
}

function exeStopRemoteQos(index) {
  console.log(TAG, 'exeStopRemoteQos')
  const remoteFeed = feeds[index]
  const currentGetStatusResult = remoteGetStatusResultArray[index]
  if (currentGetStatusResult) {
    currentGetStatusResult.nomore()
  }
  if (remoteFeed) {
    const timerId = remoteFeed.webrtcStuff.bitrate.timer
    clearInterval(timerId)
  }
}

function exeGetPeer(sessionId) {
  console.log(TAG, 'exeGetPeer')
  return tvRTC.sessions[sessionId].pluginHandler().webrtcStuff.pc
}

function exeStreamStart(sessionId, options, roomId, callbacks) {
  myCallbacks[sessionId].onlocalstream =
		typeof callbacks.onlocalstream === 'function' ? callbacks.onlocalstream : tvRTCMethod.noop
  myCallbacks[sessionId].onremotestream =
		typeof callbacks.onremotestream === 'function' ? callbacks.onremotestream : tvRTCMethod.noop
  // 获得会场分辨率
  tvvsdk_constants.resList.forEach(function(res, index, arr) {
    if (res.value === options.conf.confsize) {
      width = res.width
      height = res.height
    }
  })

  // 获得会议模式
  tvvsdk_constants.confModeList.forEach(function(m) {
    if (m.value === options.conf.mode) {
      confmode = m.mode
    }
  })

  // 校验会场比特率
  confminbr = options.conf.confminbr
  confmaxbr = options.conf.confmaxbr
  conffps = options.conf.conffps
  picmode = options.conf.picmode
  userOptions = options

  const streamstart = {
    request: 'streamstart',
    mode: confmode,
    mcufps: conffps,
    mcuheight: height,
    mcuwidth: width,
    mcuminbr: confminbr,
    mcuinitbr: confmaxbr,
    mcumaxbr: confmaxbr,
    picmode: picmode,
    picnum: 9,
    sendaudio: options.audio.sendaudio,
    recvaudio: options.audio.recvaudio,
    sendvideo: options.video.sendvideo,
    recvvideo: options.video.recvvideo,
    subscribeaudio: options.audio.subscribeaudio,
    subscribevideo: options.video.subscribevideo,
    publishaudio: options.audio.publishaudio,
    publishvideo: options.video.publishvideo,
    transport: 'udp',
    videocodec: 'H264'
  }
  console.log('exeStreamStart:', sessionId, tvRTC.sessions)
  tvRTC.sessions[sessionId].setOption(options)
  tvRTC.sessions[sessionId].pluginHandler().send({
    message: streamstart
  })
}

function exeStreamStop(sessionId) {
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    tvRTC.sessions[sessionId].pluginHandler().streamstop(true)
  }
}

function exeHangup(sessionId) {
  if (tvRTC.sessions[sessionId]) {
    tvRTC.sessions[sessionId].destroy()
  }
}

function exeInvite28181(sessionId, deviceId, callback) {
  const invite28181 = {
    request: 'invitesip',
    account: deviceId,
    mode: 2,
    mcufps: 15,
    mcuheight: 720,
    mcuwidth: 1280,
    mcuminbr: 300000,
    mcuinitbr: 2000000,
    mcumaxbr: 2000000,
    picmode: 0,
    picnum: 1,
    sendaudio: true,
    recvaudio: true,
    sendvideo: true,
    recvvideo: true,
    subscribeaudio: true,
    subscribevideo: true,
    publishaudio: true,
    publishvideo: true,
    transport: 'udp',
    videocodec: 'H264'
  }
  tvRTC.sessions[sessionId].pluginHandler().send({
    message: invite28181
  })

  const res = {}
  res.success = true
  callback(res)
}

function exeBye28181(sessionId, deviceId, callback) {
  const exeBye28181 = {
    request: 'bye',
    account: deviceId
  }
  tvRTC.sessions[sessionId].pluginHandler().send({
    message: exeBye28181
  })
  const res = {}
  res.success = true
  callback(res)
}

function exeQueryLog(sessionId, session_id, session_name, room_name, importance, type, callback) {
  const callbacks = {
    message: {
      request: 'querylog',
      sessionid: session_id,
      sessionname: session_name,
      roomname: room_name,
      importance: importance,
      type: type
    },
    success: function(result) {
      if (result.type !== 'querylogresult') {
        console.log(TAG, 'not expect msg for exeQueryLog')
        return
      }

      if (callback) {
        result.success = true
        callback(result)
      }
    },
    error: function(error) {
      console.log(error)
      if (callback) {
        callback.error(error.msg)
      }
    }
  }
  tvRTC.sessions[sessionId].pluginHandler().send(callbacks)
}

function exeTruncateLog(sessionId, callback) {
  const callbacks = {
    message: {
      request: 'truncatelog'
    },
    success: function(result) {
      const r = {}
      r['success'] = true
      callback(r)
    },
    error: function(error) {
      console.log(error)
      if (callback) {
        callback.error(error.msg)
      }
    }
  }
  tvRTC.sessions[sessionId].pluginHandler().send(callbacks)
}

module.exports = {
  // 必须在这里暴露接口，以便被外界访问，不然就不能访问
  exeInit: exeInit,
  exeJoinRoom: exeJoinRoom,
  exeQueryRoom: exeQueryRoom,
  exeQueryDevice: exeQueryDevice,
  exeCompositeRoom: exeCompositeRoom,
  exeCreateConnection: exeCreateConnection,
  exeAttachMediaStream: exeAttachMediaStream,
  exeLeaveRoom: exeHangup,
  exeShareScreen: exeShareScreen,
  exePublish: exePublish,
  exeMike: exeMike,
  exeSendData: exeSendData,
  exeSetBitrate: exeSetBitrate,
  exeSetResolution: exeSetResolution,
  exeReconfigConf: exeReconfigConf,
  exeGetAllDevices: exeGetAllDevices,
  exeGetQos: exeGetQos,
  exeInitQos: exeInitQos,
  exeStartLocalQos: exeStartLocalQos,
  exeStopLocalQos: exeStopLocalQos,
  exeStopRemoteQos: exeStopRemoteQos,
  exeStartRemoteQos: exeStartRemoteQos,
  exeGetPeer: exeGetPeer,
  exeLogin: exeLogin,
  exeLoginOut: exeLoginOut,
  exeSendSingleMessage: exeSendSingleMessage,
  exeAddMessageEventListener: exeAddMessageEventListener,
  exeGetOnlineUsers: exeGetOnlineUsers,
  exeSendRoomMessage: exeSendRoomMessage,
  exeStreamStart: exeStreamStart,
  exeStreamStop: exeStreamStop,
  exeInvite28181: exeInvite28181,
  exeBye28181: exeBye28181,
  exeQueryLog: exeQueryLog,
  exeTruncateLog: exeTruncateLog
}

function startShareScreen(sessionId, callback) {
  cleanUserOption()
  userOptions.video.type = 'window'
  userOptions.replaceVideo = true
  userOptions.screenshareFrameRate = 12

  const resp = {}
  const incomingcallResp = {}
  const callbacks = {
    media: userOptions,
    success: function(jsep) {
      resp.success = true
      callback(resp)
      isShareScreen = true
    },
    error: function(error) {
      console.log(TAG, error)
      if (error.name === 'NotAllowedError') {
        error = tvTipsConstants.cancelShareScreen
        myCallbacks[sessionId].onsharescreen(false)
      }
      resp.success = false
      resp.msg = error
      callback(resp)
      isShareScreen = false
      // 恢复原先的视频状态
      closeShareScreen(sessionId, callback)
    },
    sources: function(sources, sourcesCallback) {
      incomingcallResp.isSources = true
      incomingcallResp.sources = sources
      incomingcallResp.sourcesCallback = sourcesCallback
      console.log('incomingcallResp =======', incomingcallResp)
      callback(incomingcallResp)
    }
  }
  console.log(callbacks.media)
  tvRTC.sessions[sessionId].pluginHandler().createOffer(callbacks)
}
// 关闭屏幕共享
function closeShareScreen(sessionId, callback) {
  console.log('closeShareScreen')
  const media = {
    removeVideo: true,
    videoSend: false,
    audioSend: audioSend
  }
  const resp = {}
  const callbacks = {
    media: media,
    success: function(jsep) {
      // myCallbacks.onsharescreen(true);
      isShareScreen = false
      resp.success = true
      if (callback) { callback(resp) }
    },
    error: function(error) {
      console.log(error)
      isShareScreen = true
      resp.success = false
      resp.msg = error
      if (callback) { callback(resp) }
    }
  }
  console.log(callbacks.media)
  tvRTC.sessions[sessionId].pluginHandler().createOffer(callbacks)
}

// 消息
function onDataRecv(sessionId, data) {
  const json = JSON.parse(data)
  console.log(TAG, json)
  const sender = json.sender
  const recver = json.recver
  const type = json.type
  const roomid = json.roomid
  const platform = json.platform
  const recverPlatform = json.recverplatform
  if (roomid) {
    if (type === tvConstants.groupMessage) {
      myCallbacks[sessionId].ondata(sender, platform, json.content)
    } else if (type === tvConstants.singleMessage) {
      // 判断当前用户名和接收者是否一致
      if (recverPlatform && recverPlatform.toString() === platform.toString()) {
        myCallbacks[sessionId].ondata(sender, platform, json.content)
      } else {
        if (recver === myName) {
          myCallbacks[sessionId].ondata(sender, platform, json.content)
        }
      }
    }
  } else {
    myCallbacks[sessionId].ondata(sender, platform, json.content)
  }
}

tvRTCMethod.noop = function() {}

function tvRTCMethod() {}

function attachLocal(sessionID, callback) {
  const resp = {}
  tvRTC.sessions[sessionID].attach({
    plugin: pluginName,
    opaqueId: opaqueId,
    success: function(handleid) {
      console.log(
        TAG,
        'Plugin attached! (' +
				pluginName +
				', id=' +
				handleid +
				')'
      )
      resp.success = true
      resp.sessionid = sessionID
      return callback(resp)
    },
    error: function(error) {
      resp.success = false
      resp.msg = error
      return callback(resp)
    },
    consentDialog: function(on) {},
    mediaState: function(medium, on) {
      console.log(
        TAG,
        'RTC ' +
				(on ? 'started' : 'stopped') +
				' receiving our ' +
				medium
      )
      // media变更
      mediaStateOperation(sessionID, on, medium)
    },
    webrtcState: function(on) {
      console.log(
        TAG,
        'TVRTC says our WebRTC PeerConnection is ' +
				(on ? 'up' : 'down') +
				' now'
      )
    },
    slowLink: function(uplink, lost) {
      console.log(
        TAG,
        'TVRTC reports problems ' +
				(uplink ? 'sending' : 'receiving') +
				' packets on this PeerConnection (' +
				lost +
				' lost packets)'
      )
    },
    onmessage: function(sessionId, msg, jsep) {
      console.log(TAG, ' ::: Got a message :::', sessionId)
      console.log(TAG, msg)
      var event = msg['event']
      if (event) {
        if (event === 'joined') {
          if (typeof myCallbacks[sessionId].onjoined === 'function') {
            myCallbacks[sessionId].onjoined(msg['username'])
          }
        } else if (event === 'incomingcall') {
          let doAudio = true
          let doVideo = true
          const sdp = msg['sdp']
          const type = msg['type']
          const incomingcallResp = {}
          const offerJsep = { 'sdp': sdp, 'type': type }
          if (sdp !== null && sdp !== undefined) {
            doAudio = (sdp.indexOf('m=audio ') > -1)
            doVideo = (sdp.indexOf('m=video ') > -1)
            console.log(TAG, 'Audio ' + (doAudio ? 'has' : 'has NOT') + ' been negotiated')
            console.log(TAG, 'Video ' + (doVideo ? 'has' : 'has NOT') + ' been negotiated')
          } else {
            console.log(TAG, "This call doesn't contain an offer... we'll need to provide one ourselves")
            return
          }
          tvRTC.sessions[sessionId].pluginHandler().createAnswer({
            jsep: offerJsep,
            success: function(jsep) {
              if (jsep.type !== 'offer') {
                console.log(TAG, 'Got SDP ' + jsep.type + '! audio=' + doAudio + ', video=' + doVideo)
                const body = {
                  request: 'accept',
                  sdp: jsep.sdp,
                  type: jsep.type
                }
                tvRTC.sessions[sessionId].pluginHandler().send({
                  'message': body
                })
                if (userOptions.video.videosend) {
                  if (userOptions.video.type === 'screen' || userOptions.video.type === 'window') {
                    callback('screen start')
                  }
                }
              }
            },
            error: function(error) {
              console.log(TAG, 'WebRTC error:', error)
              if (error === 'screen stop') {
                callback('screen stop')
                // 取消弹窗
              } else if (error && error.toString().indexOf('Permission denied') !== -1) {
                callback('screen denied')
              } else {
                callback(error)
              }
            },
            sources: function(sources, sourcesCallback) {
              incomingcallResp.isSources = true
              incomingcallResp.sources = sources
              incomingcallResp.sourcesCallback = sourcesCallback
              console.log('incomingcallResp =======', incomingcallResp)
              callback(incomingcallResp)
            }
          })
        } else if (event === 'candidate') {
          const webrtcStuff = tvRTC.sessions[sessionId].pluginHandler().webrtcStuff
          const candidate = { 'candidate': msg['candidate'], 'sdpMid': msg['sdpMid'], 'sdpMLineIndex': msg['sdpMLineIndex'] }
          if (webrtcStuff.pc && webrtcStuff.remoteSdp) {
            // Add candidate right now
            console.log(TAG, 'Adding remote candidate:', candidate)
            webrtcStuff.pc.addIceCandidate(candidate)
          } else {
            // We didn't do setRemoteDescription (trickle got here before the offer?)
            console.log(TAG, "We didn't do setRemoteDescription (trickle got here before the offer?), caching candidate")
            if (!webrtcStuff.candidates) { webrtcStuff.candidates = [] }
            webrtcStuff.candidates.push(candidate)
            console.log(TAG, webrtcStuff.candidates)
          }
        } else if (event === 'destroyed') {
          console.log(TAG, 'The room has been destroyed!')
        } else if (event === 'event') {
          if (msg['error'] !== undefined && msg['error'] !== null) {
            if (msg['error_code'] === 426) {
              //	alert("no such room")
            } else {
              alert(msg['error'])
            }
          }
        } else if (event === 'incomingconfsms') {
          const sender = msg['sender']
          const content = msg['content']
          myCallbacks[sessionId].ondata(sender, '', content)
        }
      } else {
        callback(msg)
      }
    },
    onlocalstream: function(sessionId, stream, data) {
      console.log(TAG, 'onlocalstream')
      const videoTracks = stream.getVideoTracks()
      const audioTracks = stream.getAudioTracks()
      let videoSend = true
      if (videoTracks === null || videoTracks === undefined || videoTracks.length === 0) {
        videoSend = false
      }
      let audioSend = true
      if (audioTracks === null || audioTracks === undefined || audioTracks.length === 0) {
        audioSend = false
      }
      var extra = {
        audio: audioSend,
        video: videoSend
      }
      myCallbacks[sessionId].onlocalstream(sessionId, stream, extra)
    },
    onremotestream: function(sessionId, stream) {
      console.log(TAG, 'onremotestream in attachLocal', sessionId)
      const videoTracks = stream.getVideoTracks()
      const audioTracks = stream.getAudioTracks()
      let videoSend = true
      if (videoTracks === null || videoTracks === undefined || videoTracks.length === 0) {
        videoSend = false
      }
      let audioSend = true
      if (audioTracks === null || audioTracks === undefined || audioTracks.length === 0) {
        audioSend = false
      }
      var extra = {
        audio: audioSend,
        video: videoSend
      }
      myCallbacks[sessionId].onremotestream(sessionId, stream, extra)
    },
    oncleanup: function() {
    },
    ondataopen: function(data) {
      console.log(TAG, 'The DataChannel is available!')
    },
    ondata: function(data) {
      console.log(TAG, 'We got data from the DataChannel! ' + data)
      onDataRecv(sessionID, data)
    }
  })
}

// ################### 混淆开始  //###################

function mediaStateOperation(sessionId, on, medium) {
  if (!on && isShareScreen && medium === 'video') {
    exeShareScreen(false, function(res) {
      if (res.success) {
        myCallbacks[sessionId].onsharescreen(false)
      }
    })
  }
}

function exeCreateConnection(mycallback) {
  console.log(TAG, 'exeCreateConnection')
  const connectionCallbacks = {
    server: urlOptions.websocketurl,
    iceServers: [{ 'urls': urlOptions.stunurl }],
    success: function(sessionID) {
      console.log(tvRTC.sessions[sessionID])
      attachLocal(sessionID, mycallback)
    },
    error: function(error) {
      resp.success = false
      resp.msg = error
      return mycallback(resp)
    },
    destroyed: function() {
      // 退出websocket
      exeLoginOut()
      window.location.reload()
    }
  }

  new tvRTC.CreateConnection(connectionCallbacks)
}

function exeSendSingleMessage(recver, recverPlatform, operation, content, callback) {
  console.log(TAG, 'exeSendSingleMessage')
  singleMessageCallback = callback
  const resp = {}
  const message = {}
  message.sender = userOptions.username
  message.platform = userOptions.platform
  message.content = content
  message.operation = operation
  message.recverPlatform = recverPlatform
  message.recver = recver
  message.type = tvMessageConstants.typeSingle
  if (tvWs) {
    try {
      tvWs.send(JSON.stringify(message))
    } catch (err) {
      resp.success = false
      resp.msg = err
      callback(resp)
    }
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.pleaseLoginFirst
    callback(resp)
  }
}

function exeAddMessageEventListener(callback) {
  console.log(TAG, 'exeAddMessageEventListener')
  wsMessageCallback = callback
}

// 单发消息 content基础信息{operation:'',extra:''}
function exeSendData(sessionId, roomId, type, sender, recver, recverPlatform, content, callback) {
  console.log(TAG, 'exeSendData')
  const resp = {}
  var message = {}
  message.sender = sender
  message.platform = userOptions.platform
  message.content = content
  message.type = type
  message.roomid = roomId
  if (recver) {
    message.recver = recver
  }
  if (recverPlatform) {
    message.recverplatform = recverPlatform
  }
  console.log(message)
  if (tvRTC.sessions[sessionId].pluginHandler()) {
    if (recver === '') {
      const confsms = {
        request: 'confsms',
        content: content,
        room: roomId,
        sender: sender,
        receiver: 'all'
      }

      tvRTC.sessions[sessionId].pluginHandler().send({
        'message': confsms
      })
    } else {
      const sms = {
        request: 'confsms',
        content: content,
        room: roomId,
        sender: sender,
        receiver: recver
      }

      tvRTC.sessions[sessionId].pluginHandler().send({
        'message': sms
      })
    }

    resp.success = true
    callback(resp)
  } else {
    resp.success = false
    resp.msg = tvTipsConstants.pleaseConnectionServer
    callback(resp)
  }
}
